/**
 * Copyright (c) 2012-2013 All Rights Reserved.
 */
package net.ifunit.generate.task;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.ifunit.generate.model.Column;
import net.ifunit.generate.model.Table;
import net.ifunit.generate.table.TableUtil;
import net.ifunit.generate.util.StringUtil;
import net.ifunit.generate.velocity.VelocityUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 默认的生成任务
 * 
 * @author wy
 * @version v 0.1 2013-9-23 下午12:45:22 wy Exp $
 */
public class DefaultGenerateTask implements GenerateTask {

    /** 日志对象 */
    protected final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * @see net.ifunit.generate.task.GenerateTask#generate(net.ifunit.generate.task.Task,
     *      java.lang.String)
     */
    @Override
    public void generate(Task task, String tableName) {

        Map<String, Object> params = getCustomParams(task);

        String entity = StringUtil.getFirstUpper(StringUtil.name(tableName));

        String entityDefine = StringUtil.getFirstLower(entity);

        Table t = TableUtil.getTable(tableName);

        if (t.getPrimaryList().size() > 1
            && !("entityTask".equalsIgnoreCase(task.getName())
                 || "daoTask".equalsIgnoreCase(task.getName())
                 || "daoImplTask".equalsIgnoreCase(task.getName()) || "mapperTask"
                .equalsIgnoreCase(task.getName()))) {
            return;
        }

        params.put("entity", entity);
        params.put("entityDefine", entityDefine);
        params.put("entityComment", t.getDesc());
        params.put("serialVersionUID", StringUtil.getSerialVersionUID());
        params.put("table", tableName);
        //命名
        params.put("name", StringUtil.class);
        //字符串
        params.put("stringUtils", StringUtils.class);

        StringBuilder entityImport = new StringBuilder();

        for (Column column : t.getColumnList()) {
            if (column.getTypeClass().getName().startsWith("java.lang")) {
                continue;
            } else if (entityImport.indexOf(column.getTypeClass().getName()) != -1) {
                continue;
            } else if (column.getColumn().equalsIgnoreCase("ID")
                       || column.getColumn().equalsIgnoreCase("createUser")
                       || column.getColumn().equalsIgnoreCase("createTime")
                       || column.getColumn().equalsIgnoreCase("modifyUser")
                       || column.getColumn().equalsIgnoreCase("modifyTime")) {
                continue;
            }
            entityImport.append("import " + column.getTypeClass().getName() + ";"
                                + System.getProperty("line.separator", "\n"));
        }
        params.put("entityImport", entityImport.toString());
        params.put("columnList", t.getColumnList());
        params.put("primaryList", t.getPrimaryList());
        params.put("autoPrimaryColumn", t.getAutoPrimaryColumn());
        params.put("autoPrimary", t.isAutoPrimary());
        params.put("notPrimaryList", t.getNotPrimaryList());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        params.put("now", new SimpleDateFormat("yyy-MM-dd "
                                               + (calendar.get(Calendar.HOUR_OF_DAY) > 12 ? "下午"
                                                   : "上午") + " HH:mm:ss").format(new Date()));
        String content = getContent(task, params);
        writeFile(task, content, entity);
    }

    /**
     * 参数
     * 
     * @param task
     * @return
     */
    protected Map<String, Object> getCustomParams(Task task) {
        Map<String, Object> params = new HashMap<String, Object>();
        //公共属性
        Map<String, String> propertiesMap = TaskUtil.getPropertiesmap();
        params.putAll(propertiesMap);
        //任务
        Map<String, Task> taskMap = TaskUtil.getTaskmap();
        params.putAll(taskMap);
        //任务的私有属性
        params.putAll(task.getProperties());
        params.put("task", task);
        return params;
    }

    /**
     * 获取生成的模板内容
     * 
     * @param task
     * @param params
     * @return
     */
    protected String getContent(Task task, Map<String, Object> params) {
        return VelocityUtil.createUTF8(task.getTemplate(), params).toString();
    }

    /**
     * 文件保存路径
     * 
     * @param task
     * @param entity
     * @return
     */
    protected String getFilePath(Task task, String entity) {
        return task.getPath() + File.separator + task.getPrefix() + entity + task.getSuffix() + "."
               + task.getExt();
    }

    /**
     * 写入文件
     * 
     * @param task
     * @param content
     * @param entity
     */
    protected void writeFile(Task task, String content, String entity) {
        File file = new File(getFilePath(task, entity));

        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        if (!file.exists()) {
            try {
                file.createNewFile();
            }
            catch (IOException e) {
                log.error("创建" + file.getPath() + "失败");
            }
        }

        FileOutputStream fos = null;
        OutputStreamWriter out = null;
        try {
            fos = new FileOutputStream(file);
            out = new OutputStreamWriter(fos, "UTF-8");
            out.write(content.toString());
        }
        catch (FileNotFoundException e) {
            log.error("找不到文件" + file.getPath());
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                }
                catch (IOException e) {
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                    fos.flush();
                }
                catch (IOException e) {
                }
            }
        }
        log.info("文件{}生成完成", file.getPath());
    }

}
